package com.iring.service.pbx;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.gson.Gson;
import com.iring.domain.config.prop.UDPProperties;
import com.iring.dao.pbx.UDPTaskDao;
import com.iring.dao.vos.CommonVosDao;
import com.iring.domain.pbx.udprec.UdpBackInfo;
import com.iring.domain.pbx.udpsend.ParamVO;
import com.iring.util.common.StringUtil;

/**
 * udp工具类
 *
 * @author wanggan
 */
@Component
public class UdpService {

    private static final Logger logger = LoggerFactory.getLogger(UdpService.class);

    @Autowired
    UDPTaskDao task;

    @Autowired
    CommonVosDao commonVosDao;

    @Autowired
    UDPProperties udpProperties;

    private static Gson gson = new Gson();

    private byte[] buffer = new byte[1024];



    public Integer sendToClientStatus(ParamVO paramVO) throws SocketException {
        DatagramSocket ds = new DatagramSocket(null);

        String jsonstr = gson.toJson(paramVO.getUdpTaskInfo());
        buffer =jsonstr.getBytes();

        DatagramPacket packet = null;
        try {
            ds.setReuseAddress(true);
            ds.bind(new InetSocketAddress(paramVO.getServerport() ));
            packet = new DatagramPacket(buffer, buffer.length,
                    InetAddress.getByName(paramVO.getClientip()), paramVO.getClientport());
            // 设置新监听端口的超时
            ds.send(packet);
        } catch (UnknownHostException e) {
            logger.info("unknown host exception..{}",e);
        } catch (IOException e) {
            logger.info("io exception..{}",e);
        } finally {
            ds.close();
        }
        return listenRandom(paramVO);
    }
    /**
     * 发送至客户端
     *
     * @param paramVO
     *            {@link ParamVO}
     * @return 返回结果
     * @throws SocketException socket异常返回上层调用抛出
     */
    private Integer listenRandom(ParamVO paramVO) throws SocketException {
        Integer randPort = paramVO.getUdpTaskInfo().getRandomport();
        String mac = paramVO.getMac();
        buffer = gson.toJson(paramVO.getUdpTaskInfo()).getBytes();
        logger.info("listen random  port={}", randPort);
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        String retstr = null;
        DatagramSocket dss = null;
        try {
            dss = new DatagramSocket(null);
            dss.setReuseAddress(true);
            // 设置新监听端口的超时
            dss.setSoTimeout((int) (udpProperties.getLinkFirstTimeOut()*1000));
            dss.bind(new InetSocketAddress(randPort));
            dss.receive(packet);
            retstr = new String(packet.getData(), 0, packet.getLength());
            dss.close();
        } catch (Exception e) {
            logger.info("time out exception.. ");
            // 新建监听
            DatagramSocket ds = null;
            try {
                ds = new DatagramSocket(null);
                ds.setReuseAddress(true);
                // 设置新监听端口的超时
                ds.setSoTimeout((int) (udpProperties.getLinkSecondTimeOut()*1000));
                ds.bind(new InetSocketAddress(randPort));
                // 添加任务
                if (task.isHaveTask(mac)) {
                    task.removeTask(mac);
                }
                task.addTask(mac, paramVO.getUdpTaskInfo());
                ds.receive(packet);
                retstr = new String(packet.getData(), 0, packet.getLength());
            } catch (IOException e1) {
                logger.info("io exception ..");
            } finally {
                if (task.isHaveTask(mac)) {
                    task.removeTask(mac);
                }
                ds.close();
            }
        } finally {
            logger.info("finally..");
        }
        return dealResult(retstr, mac);
    }

    public Integer dealResult(String retstr, String mac) {
        Integer status = -1;
        if(StringUtil.isEmpty(retstr)){
            return status;
        }
        logger.info("udp client to server resstr={}",retstr);
        // json泛型解析
        UdpBackInfo udpBackInfo = gson.fromJson(retstr,UdpBackInfo.class);
        if (mac.equals(udpBackInfo.getMac())) {
            status = udpBackInfo.getStatus();
        }
        return status;
    }

    /**
     * 获取随机端口
     *
     * @return 客户端返回结果
     */
    public Integer getRandomPort() {
        ServerSocket serverSocket = null;
        int port = 0;
        try {
            serverSocket = new ServerSocket(0);
            port = serverSocket.getLocalPort();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return port;
    }
}
